package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.CountDownTimer;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.utils.Pair;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 兑棋
 */
public class ExchangeRoom extends Room {

    private static final int WIN_NUM = 8; //获胜层数
    private final List<int[]> moveArrayList = new ArrayList<>(); // 移动标记
    private int[][] numGrids = null;
    private Pair<Integer, Integer> chooseIndex = null;
    private int[] limitArr;

    public ExchangeRoom(String roomName) {
        super(roomName, "夏日新棋八卦系列之”兑“", "兑棋", GridsUtils.createEmptyGrids(10,10), true, true);
    }

    @Override
    public String getRuleText() {
        return "《兑棋》规则说明\n" +
                "10x10方格棋盘。\n" +
                "红蓝两色纯数字棋子，黑方控制红色棋子，白方控制蓝色。\n" +
                "棋子数字范围1-"+ WIN_NUM +"，称为N级塔（N为棋子数字），\n" +
                "开局双方各有两个塔位于棋盘对角，黑先白后轮流行棋。\n" +
                "行动开始前自动将己方所有1级塔生长为2级塔。\n" +
                "接着玩家必须选择己方的一个塔朝一个方向进行【播种】\n" +
                "播种方向为所选棋子上下左右和四个斜角，播种落点为所选方向1-N格（N为棋子数字）。\n" +
                "【播种】移除所选的塔，目标方向1-N格，扶起1级塔，己方塔数字加1，敌方塔数字-1。\n" +
                "【连锁】若播种末格为己方棋塔，玩家必须控制该塔并另选一个线的方向继续播种，直到末格为敌方、空格或者出界。\n" +
                "先扶起一座"+WIN_NUM+"层塔的玩家获胜！";
    }

    @Override
    public String getGameInfo() {
        signList.clear();
        curGrids = GridsUtils.copyGrids(originGrids);
        //画棋子
        if (numGrids != null){
            for (int i = 0; i < numGrids.length; i++) {
                for (int j = 0; j < numGrids[i].length; j++) {
                    if (numGrids[i][j] != 0){
                        curGrids[i][j] = numGrids[i][j] > 0 ? 1 : 2;
                        signList.add(new TextSign(getIndex(i, j), String.valueOf(Math.abs(numGrids[i][j])), numGrids[i][j] > 0 ? ColorCost.CHESS_RED : ColorCost.CHESS_BLUE));
                        if (numGrids[i][j] == WIN_NUM || numGrids[i][j] == -WIN_NUM){
                            signList.add(new ColorSign(getIndex(i, j), ColorCost.GOLDEN_WIN));
                        }
                    }
                }
            }
        }
        //画选中效果
        if (chooseIndex != null){
            //画选中框
            signList.add(new GroundSign(getIndex(chooseIndex.first, chooseIndex.second), ColorCost.TRANSPARENT, ColorCost.NEW_PUT_POINT, 1.0f, 0, 1));
            //画落点提示
            for (int i = 0; i < curGrids.length; i++) {
                for (int j = 0; j < curGrids[i].length; j++) {
                    if (isInSeedingPath(i,j)){
                        signList.add(new TextSign(getIndex(i, j), "◌", ColorCost.NEW_PUT_POINT_LIGHT));
                    }
                }
            }
        }
        //画路径提示
        for (int[] moveArray : moveArrayList) {
            signList.add(new LineSign(moveArray[0], moveArray[1], ColorCost.NEW_PUT_POINT_LIGHT, 1));
        }
        return super.getGameInfo();
    }

    @Override
    protected void onStartPrepare() {
        numGrids = GridsUtils.createEmptyGrids(curGrids.length,curGrids[0].length);
        numGrids[1][0] = 2;
        numGrids[8][9] = 2;
        numGrids[0][8] = -3;
        numGrids[9][1] = -1;
        noticeBlackMove();
        //nextAction(1);
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        moveArrayList.clear();
        numGrids = null;
        chooseIndex = null;
        limitArr = null;
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (chooseIndex == null){
            if (value == 1 && numGrids[row][col] > 0){
                chooseIndex = new Pair<>(row, col);
            }
            if (value == 2 && numGrids[row][col] < 0){
                chooseIndex = new Pair<>(row, col);
            }
            noticeAllRefreshGameInfo();
        }
        else{
            if (isInSeedingPath(row, col)){
                seedingTower(row,col);
            }
            else if (limitArr == null){ //limitArr为空，代表不是连锁播种，才可以重置选择
                chooseIndex = null;
                noticeAllRefreshGameInfo();
            }
        }
    }

    //播种这个塔
    private void seedingTower(int row, int col) {
        boolean isContinue = false; //是否连锁？
        int dis = Math.abs(numGrids[chooseIndex.first][chooseIndex.second]); //塔的高度
        int dNum = Integer.signum(numGrids[chooseIndex.first][chooseIndex.second]); //塔的正负
        int dR = Integer.signum(row - chooseIndex.first); //塔的行方向
        int dC = Integer.signum(col - chooseIndex.second); //塔的列方向
        int finalRow = row,finalCol = col; //最终落点
        //移除选中塔
        numGrids[chooseIndex.first][chooseIndex.second] = 0;
        //遍历播种范围格子
        for (int i = 1; i <= dis; i++) {
            int newRow = chooseIndex.first + i * dR; //新格子行
            int newCol = chooseIndex.second + i * dC; //新格子列
            if (newRow < 0 || newRow >= numGrids.length || newCol < 0 || newCol >= numGrids[0].length){
                isContinue = false; //超出界外直接结束行动
                break;
            }
            //记录播种到的最终点
            finalRow = newRow;
            finalCol = newCol;
            if (numGrids[newRow][newCol] == 0){
                numGrids[newRow][newCol] = dNum; //播种到空格，扶起1级塔
            }
            else {
                numGrids[newRow][newCol] += dNum; //播种到数字 自己塔的高度增加，对方塔的高度降低
                if (i == dis && Integer.signum(numGrids[newRow][newCol]) == dNum){
                    isContinue = true; //最后一格是己方塔时，连锁播种
                }
            }
        }
        //添加移动箭头
        if (moveArrayList.size()>0 && moveArrayList.get(0)[2] != dNum){
            moveArrayList.clear();
        }
        moveArrayList.add(new int[]{getIndex(chooseIndex.first, chooseIndex.second), getIndex(finalRow, finalCol),dNum});
        chooseIndex = null;
        //判断是否获胜
        if (!checkWin()){
            //连锁播种
            if (isContinue){
                chooseIndex = new Pair<>(finalRow, finalCol);
                limitArr = new int[]{dR,dC};
                noticeAllRefreshGameInfo();
            }
            //切换行动方
            else {
                limitArr = null;
                if (cur == 1){
                    noticeNoMove();
                    nextAction(2);
                }
                else {
                    noticeNoMove();
                    nextAction(1);
                }
            }
        }
    }

    //判断是否获胜
    private boolean checkWin() {
        int blackCount = GridsUtils.getDataCount(numGrids, 1,2,3,4,5,6,7,8,9,10);
        int whiteCount = GridsUtils.getDataCount(numGrids, -1,-2,-3,-4,-5,-6,-7,-8,-9,-10);
        if (blackCount == 0){
            doOver(WinMode.WHITE_WIN, "黑方没有塔了，白方获胜！");
            return true;
        }
        else if (whiteCount == 0){
            doOver(WinMode.BLACK_WIN, "白方没有塔了，黑方获胜！");
            return true;
        }
        else {
            for (int[] numGrid : numGrids) {
                for (int i : numGrid) {
                    if (i>=WIN_NUM){
                        doOver(WinMode.BLACK_WIN, "黑方成功扶起最高层塔获胜！");
                        return true;
                    }
                    else if (i <= -WIN_NUM){
                        doOver(WinMode.WHITE_WIN, "白方成功扶起最高层塔获胜！");
                        return true;
                    }
                }
            }
        }
        return false;
    }

    //切换行动方
    private void nextAction(int tar) {
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                if (tar == 1){
                    naturalGrowth(1); //开局先让黑方的塔生长
                    noticeBlackMove(); //默认通知黑方先行动
                }
                else if (tar == 2){
                    naturalGrowth(2);
                    noticeWhiteMove();
                }
            }
        }, 300);
    }

    // 己方所有1级塔 生长为2级塔
    private void naturalGrowth(int cur) {
        stepAdd();
        for (int i = 0; i < numGrids.length; i++) {
            for (int j = 0; j < numGrids[i].length; j++) {
                if (numGrids[i][j] == 1 && cur == 1){
                    numGrids[i][j] = 2;
                }
                else if (numGrids[i][j] == -1 && cur == 2){
                    numGrids[i][j] = -2;
                }
            }
        }
    }

    //目标点在当前所选的棋子播种范围内
    private boolean isInSeedingPath(int i, int j) {
        if (i == chooseIndex.first && j == chooseIndex.second) return false; //选中点原位置不在播种范围内
        if (limitArr != null && (Integer.signum(i - chooseIndex.first) == limitArr[0] && Integer.signum(j - chooseIndex.second) == limitArr[1] || Integer.signum(i - chooseIndex.first) == -limitArr[0] && Integer.signum(j - chooseIndex.second) == -limitArr[1])) return false; //限制方向
        int dis = Math.abs(numGrids[chooseIndex.first][chooseIndex.second]);
        if (Math.abs(i - chooseIndex.first) <= dis && Math.abs(j - chooseIndex.second) <= dis){
            if (i == chooseIndex.first || j == chooseIndex.second){
                return true;
            }
            if (Math.abs(i - chooseIndex.first) == Math.abs(j - chooseIndex.second)){
                return true;
            }
        }
        return false;
    }
}
